﻿using System;
using System.Windows.Input;

namespace Thinktecture.DataForm
{
    public class DelegateCommand : ICommand
    {
        internal Func<object, bool> _canExecuteHandler;
        internal Action<object> _executeHandler;
        private bool _canExecuteCache;

        public DelegateCommand()
        {
        }

        public DelegateCommand(Action<object> executeHandler)
        {
            this._executeHandler = executeHandler;
        }

        public DelegateCommand(Func<object, bool> canExecuteHandler, Action<object> executeHandler)
        {
            this._executeHandler = executeHandler;
            this._canExecuteHandler = canExecuteHandler;
        }

        #region ICommand Members

        public bool CanExecute(object parameter)
        {
            if (_canExecuteHandler == null)
                return true;
            bool temp = _canExecuteHandler(parameter);

            if (_canExecuteCache != temp)
            {
                _canExecuteCache = temp;
                if (CanExecuteChanged != null)
                {
                    CanExecuteChanged(this, new EventArgs());
                }
            }

            return _canExecuteCache;
        }

        public event EventHandler CanExecuteChanged;

        public void Execute(object parameter)
        {
            _executeHandler(parameter);
        }

        #endregion
    }
    
    public class ActionCommand : DelegateCommand
    {
        public ActionCommand() : base()
        {
        }
        private ActionCommand(Func<object, bool> canExecuteHandler, Action<object> executeHandler) : base(canExecuteHandler, executeHandler)
        {
        }
        private ActionCommand(Action<object> executeHandler) : base(executeHandler)
        {
        }
        public void SetExecutedHandler(Func<object, bool> canExecuteHandler, Action<object> executeHandler)
        {
            _canExecuteHandler = canExecuteHandler;
            _executeHandler = executeHandler;
        }
        
        public bool CanExecuteAction(DataFormAction action, object parameter)
        {
            return this.CanExecute(new ActionParameter { Action = action, Parameter = parameter });
        }

        public void ExecuteAction(DataFormAction action, object parameter)
        {
            if (_executeHandler != null)
                _executeHandler(new ActionParameter { Action = action, Parameter = parameter });
        }
    }

    public class ActionParameter
    {
        public DataFormAction Action { get; set; }
        public object Parameter { get; set; }
    }
}
